package cn.stylefeng.guns.sys.modular.system.service.impl;

import cn.stylefeng.guns.base.pojo.page.LayuiPageFactory;
import cn.stylefeng.guns.base.pojo.page.LayuiPageInfo;
import cn.stylefeng.guns.sys.core.util.DingdingAttendUtil;
import cn.stylefeng.guns.sys.core.util.TimeUtil;
import cn.stylefeng.guns.sys.core.util.UUIDUtils;
import cn.stylefeng.guns.sys.modular.system.entity.BtyDingdingDayAttend;
import cn.stylefeng.guns.sys.modular.system.entity.BtyDingdingDayEmp;
import cn.stylefeng.guns.sys.modular.system.entity.BtyDingdingMonthAttend;
import cn.stylefeng.guns.sys.modular.system.mapper.BtyDingdingDayAttendMapper;
import cn.stylefeng.guns.sys.modular.system.model.params.BtyDingdingDayAttendParam;
import cn.stylefeng.guns.sys.modular.system.model.params.BtyDingdingDayEmpParam;
import cn.stylefeng.guns.sys.modular.system.model.result.BtyDingdingDayAttendResult;
import  cn.stylefeng.guns.sys.modular.system.service.BtyDingdingDayAttendService;
import cn.stylefeng.guns.sys.modular.system.service.BtyDingdingDayDeptService;
import cn.stylefeng.guns.sys.modular.system.service.BtyDingdingDayEmpService;
import cn.stylefeng.roses.core.util.ToolUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dingtalk.api.response.OapiAttendanceGetcolumnvalResponse;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.*;


/**
 * <p>
 * 钉钉;前三十天，人员出勤数据 服务实现类
 * </p>
 *
 * @author wjk
 * @since 2022-05-30
 */
@Service
public class BtyDingdingDayAttendServiceImpl extends ServiceImpl<BtyDingdingDayAttendMapper, BtyDingdingDayAttend> implements BtyDingdingDayAttendService {

    private static Logger logger = LoggerFactory.getLogger(BtyDingdingDayAttendServiceImpl.class);

    @Resource
    private DingdingAttendUtil dingdingAttendUtil;

    @Autowired
    private BtyDingdingDayEmpService btyDingdingDayEmpService;


    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    SimpleDateFormat sdfYMD = new SimpleDateFormat("yyyy-MM-dd");


    //    //标准一天工作时长(分钟)，默认9小时，即540分钟；
//    private static final Double STANDARD_WORKING_MINUTES = Double.valueOf("540");

    //2022-05-25 新需求，标准一天工作时长(分钟)，默认7.5 小时，即540分钟；
    private static final Double STANDARD_WORKING_MINUTES = Double.valueOf("450");

    //大于此工作时长算，半天工作时长(分钟)，默认1小时，即60分钟；
    private static final Double HALF_WORKING_MINUTES = Double.valueOf("60");


    //标准一天出勤 1天
    private static final Double STANDARD_ATTEND_WORK_DAY = Double.valueOf("1");
    //标准半天出勤 0.5天
    private static final Double HALF_ATTEND_WORK_DAY = Double.valueOf("0.5");
    //标准无出勤 0天
    private static final Double NOT_ATTEND_WORK_DAY = Double.valueOf("0");

    //三次打卡时间两两打卡时间只差超过30分钟，此才可算考勤一天，考勤；
    private static final Long THREE_WORKING_MINUTES_POOR = 30L;
    //弃用，两打卡时间只差超过6小时，即360 分钟 此才可算考勤一天，算漏打卡两次；
    // private static final Long TWO_WORKING_MINUTES_POOR = 360L;

    //两打卡时间只差超过7.5小时，即360 分钟 此才可算考勤一天，算漏打卡两次；
    private static final Long TWO_WORKING_MINUTES_POOR = 450L;

    //两次打卡时间若是在15分钟之内，则算一次考勤打卡
    private static final Double FIFTEEN_MINUTES = Double.valueOf("15");

    @Override
    public void add(BtyDingdingDayAttendParam param){
        BtyDingdingDayAttend entity = getEntity(param);
        this.save(entity);
    }

    @Override
    public void delete(BtyDingdingDayAttendParam param){
        this.removeById(getKey(param));
    }

    @Override
    public void update(BtyDingdingDayAttendParam param){
        BtyDingdingDayAttend oldEntity = getOldEntity(param);
        BtyDingdingDayAttend newEntity = getEntity(param);
        ToolUtil.copyProperties(newEntity, oldEntity);
        this.updateById(newEntity);
    }

    @Override
    public BtyDingdingDayAttendResult findBySpec(BtyDingdingDayAttendParam param){
        return null;
    }

    @Override
    public List<BtyDingdingDayAttendResult> findListBySpec(BtyDingdingDayAttendParam param){
        return null;
    }

    @Override
    public LayuiPageInfo findPageBySpec(BtyDingdingDayAttendParam param){
//        Page pageContext = getPageContext();
//        IPage page = this.baseMapper.customPageList(pageContext, param);
//        return LayuiPageFactory.createPageInfo(page);

        List<BtyDingdingDayAttendResult> list = this.baseMapper.customPageList(param);
        LayuiPageInfo layuiPageInfo = new LayuiPageInfo();
        layuiPageInfo.setData(list);
        return layuiPageInfo;
    }

    /**
     * 开始同步半天妖部门的员工的月度考勤信息
     * 月度,每一天的数据
     * @author
     * @Date 2022-05-30
     *  钉钉 写成定时任务；
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, String> addBtyDingdingDayAttend(BtyDingdingDayAttendParam param) throws InterruptedException {
        // 查询获取月份，默认上个月
        String  lastMonth = param.getAttendYearMonth();
        if(ToolUtil.isEmpty(param.getAttendYearMonth())){
            // 若没有传参数，则默认上月月的数据
            lastMonth  = TimeUtil.getLastMonthStr();
        }
        String thisMonth = lastMonth+"01";
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        Date date = new Date();
        try {
            date = format.parse(thisMonth);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        // 根据根据月份取出当月的第一天和最后一天
        String monthFirstDay = TimeUtil.getMonthFirstDayStr(date);
        String monthLastDay = TimeUtil.getMonthLastDayStr(date);

        // 查找这个月的人员数据
        BtyDingdingDayEmpParam btyDingdingDayEmpParam = new BtyDingdingDayEmpParam();
        btyDingdingDayEmpParam.setAttendYearMonth(lastMonth);
        btyDingdingDayEmpParam.setDeptId(param.getDid());
//        // 获取半天妖所有的人员列表（所有）
//        List<BtyDingdingDayEmp> BtyDingdingDayEmpList = BtyDingdingDayEmpService.listMonthAll(BtyDingdingDayEmpParam);

        // 获取半天妖所有的人员列表（所有不重复数据）
        List<BtyDingdingDayEmp> btyDingdingDayEmpList = btyDingdingDayEmpService.listMonthAllNotRepeat(btyDingdingDayEmpParam);

        //获取当月人员所有列表
        List<BtyDingdingDayAttend> AttendListAllAll = new ArrayList<BtyDingdingDayAttend>(){};
        long t1=System.currentTimeMillis();
        logger.info("获取半天妖用户:{},考勤数据:{}-预计用时120分钟，请耐心等待.......若中途停止，则只获取了员工和部门信息，无法获取员工考勤信息",btyDingdingDayEmpList.size(),AttendListAllAll.size());

        int empListLength = btyDingdingDayEmpList.size() - 1;

        //根据月份，去删除数据当月的数据
        Integer delSize = this.baseMapper.deleteByYearMonth(lastMonth);

        for(int i = 0,lsize = btyDingdingDayEmpList.size();i<lsize;i++ ){

            BtyDingdingDayEmp btyDingdingDayEmp = btyDingdingDayEmpList.get(i);

            OapiAttendanceGetcolumnvalResponse rsp = dingdingAttendUtil.getColumnvalList(String.valueOf(btyDingdingDayEmp.getEmpId()),monthFirstDay,monthLastDay);
            //logger.info("获取用户考勤数据{}-{}-{}",Thread.currentThread().getName(),BtyDingdingDayEmp.getEmpName(),BtyDingdingDayEmp.getEmpPhone());
            Map map = (Map) JSON.parse(rsp.getBody());
            Integer ercode = (Integer) map.get("errcode");
            if(ercode!=0){
                logger.error("{}-{}获取考勤失败。case:{}",btyDingdingDayEmp.getEmpId(),btyDingdingDayEmp.getEmpName(),map.get("errmsg"));
                continue;
            }
            Map kqresult = (Map) map.get("result");
            //10col
            List<Map> list = (List) kqresult.get("column_vals");

            //获取当月人员所有列表
            //获取，此员工，这个月，多少天内，默认创建多少条考勤数据；
            List<BtyDingdingDayAttend> empAttendListMonthAll = setEmpAttendListMonthAllBase(btyDingdingDayEmp,lastMonth);
            //将这个员工获取的这个月的考勤数据存储到列表中；
            List<BtyDingdingDayAttend> empAttendListMonthAllInfo = setEmpAttendListMonthAllInfo(empAttendListMonthAll,btyDingdingDayEmp,list);
            //存储到总数据中
            AttendListAllAll.addAll(empAttendListMonthAllInfo);
            if(i%10 == 0){
                //System.out.println("钉钉数据获取中-------------------》"+i);
                logger.info("钉钉数据获取中-------------------》"+i);
            }

            // 集合满100人或者最后一人
            if (i%100 == 0 || i == empListLength) {

                // 将这个月人员数据进行处理
                for(BtyDingdingDayAttend dddda:AttendListAllAll){

                    //根据打卡次数和打卡时间，计算出勤天数
                    dddda = calculateAttendanceDays(dddda);
                    // 若有请假假状态
                    if(dddda.getAskLeaveStatus() == 1){
                        //计算请假天数
                        dddda = calculateAskLeaveDays(dddda);
                    }

                }

                simpleSqlInsertBatch(AttendListAllAll);

                AttendListAllAll.clear();
            }
            Thread.sleep(10);

        }
//        long t2=System.currentTimeMillis();
//        long t=(t2-t1)/1000;
//        logger.info("获取半天妖用户:{},考勤数据:{}-用时:{}",btyDingdingDayEmpList.size(),AttendListAllAll.size(),t);
//
//
//        long t3=System.currentTimeMillis();
//
//
//        long t4=System.currentTimeMillis();
//        long t5=(t3-t4)/1000;
//
//        logger.info("处理半天妖用户:{},考勤数据:{}-用时:{}",btyDingdingDayEmpList.size(),AttendListAllAll.size(),t5);
//
//        // 存储这个月人员考勤数据
//        long t6=System.currentTimeMillis();
//
//        long t7=System.currentTimeMillis();
//        long t8=(t7-t6)/1000;
//        logger.info("存储半天妖用户:{},考勤数据:{}-用时:{}",btyDingdingDayEmpList.size(),AttendListAllAll.size(),t8);
//
        long t7=System.currentTimeMillis();
        long t9=(t7-t1)/1000;
        logger.info("汇总--------->半天妖用户:{},用时:{}",empListLength,t9);
        Map<String, String> mapResult = new HashMap<>();
        mapResult.put("size",String.valueOf(empListLength));
        return mapResult;
    }




    /**
     * 获取月度考勤信息,从日数据表中
     * @param param
     * @return
     */
    @Override
    public List<BtyDingdingMonthAttend> mergeAttendYearMonth(BtyDingdingDayAttendParam param) {
        List<BtyDingdingMonthAttend> list = this.baseMapper.mergeAttendYearMonth(param);
        return list;
    }

    /**
     * 计算请假天数
     * @param dddda
     * @return
     */
    private BtyDingdingDayAttend calculateAskLeaveDays(BtyDingdingDayAttend dddda) {

        String requestNote = dddda.getRequestNote();
//        logger.info("日期：------>{}",dddda.getAttendDay());
//        logger.info("假：------>{}",requestNote);
//        logger.info("工作天：------>{}",dddda.getAttendWorkDay());

        // 若有假期
        if(requestNote.contains("假")){
            //将有假期状态标记
            dddda.setAskLeaveStatus(1);
            String[] requestNoteArr = requestNote.split(",");
            for(String note:requestNoteArr){
                //如果有假出，计算出假的天数
                if(note.contains("假")){

                    //事假03-19 07:00到03-19 22:00 13.5小时
                    //年假03-30 07:30到03-30 22:00 1天
                    String[] noteArr = note.split(" ");

                    if(noteArr[3].contains("小时")){
                        // 5小时以上不包括5小时算1天；
                        Double noteTime = Double.valueOf(noteArr[3].replace("小时",""));

                        if(Double.doubleToLongBits(noteTime) > Double.doubleToLongBits(Double.valueOf("5"))){
                            if(dddda.getAttendWorkDay().equals(Double.valueOf("0"))){
                                dddda.setAskLeaveDay(Double.valueOf("1"));
                            }
                            //查看当天是否有工时，若有工时，则算取出工时的假
                            if(Double.doubleToLongBits(dddda.getAttendWorkDay()) > Double.doubleToLongBits(Double.valueOf("0"))){
                                Double askLeaveDay = Double.valueOf("1") - dddda.getAttendWorkDay();
                                dddda.setAskLeaveDay(askLeaveDay);
                            }
                        }
                        //1-5小时请假，算0.5天，
                        if(Double.doubleToLongBits(Double.valueOf("5")) >= Double.doubleToLongBits(noteTime) && Double.doubleToLongBits(noteTime)>= Double.doubleToLongBits(Double.valueOf("1"))){
                            dddda.setAskLeaveDay(Double.valueOf("0.5"));
                        }
                    }

                    // 天计算
                    if(noteArr[3].contains("天")){
                        //
                        Double noteTime = Double.valueOf(noteArr[3].replace("天",""));
                        if(Double.doubleToLongBits(noteTime)>Double.doubleToLongBits(Double.valueOf("1"))){
                            dddda.setAskLeaveDay(Double.valueOf("1"));
                        }
                        if(Double.doubleToLongBits(Double.valueOf("1"))>=Double.doubleToLongBits(noteTime)){
                            dddda.setAskLeaveDay(noteTime);
                        }

                    }
                }
            }
        }
        return dddda;
    }

    /**
     *
     * 根据打卡次数和打卡时间，计算出勤天数
     * @param dddda
     * @return
     */
    @Override
    public BtyDingdingDayAttend calculateAttendanceDays(BtyDingdingDayAttend dddda) {
        // 将钉钉获取的迟到次数制空，迟到，自己判断
        dddda.setLateNum(0);
        //  判断是否有班次，

        // 判断是否有正常班次
        
        BtyDingdingDayAttendAttendShiftNote shiftNote = calculateShiftNote(dddda);

        //  判断打卡几次
        // 工时的计算
        //  若没有班次，则处理为自由工时，自由工时

        // 计算打卡次数
        List<Date> listDate = calculateListDateAll(dddda);

        // 默认工时 0 ；
        Double attendWorkMinutes = new Double("0");

        //迟到次数
        int lateNum = 0;

        // 大于四次打卡
        if(listDate.size() > 4){
            // 获取第一次打卡，获取最后一次打卡
            attendWorkMinutes = compareTwoDateMinutes(listDate.get(0) ,listDate.get(listDate.size()-1));
            // 工作时长等于，最后一次打卡时间减第一次打卡时间，
            dddda.setAttendWorkMinutes(attendWorkMinutes);

            // 若没有班次，则按照打卡次数计算，
            if(shiftNote.getFlag() == false ){
                //当天打卡状态正常
                dddda.setAttendStatus(0);
                dddda.setAttendWorkDay(STANDARD_ATTEND_WORK_DAY);
            }

            // 若有班次，则按照班次计算，迟到问题
            if(shiftNote.getFlag() == true ){

                // 判断第一次打卡时间，
                if(ToolUtil.isNotEmpty(dddda.getTimeOneNote())&&dddda.getTimeOneNote().contains("迟到")){
                    //计算迟到分钟数
                    Double lateMinutes = compareTwoDateMinutes(shiftNote.getTimeOne() ,dddda.getTimeOne());
                    // 若迟到小于等于30 分钟，则算迟到，若迟到，大于30分钟，则不算迟到
                    if(lateMinutes <= 30){
                        lateNum ++ ;
                    }
                }

                // 判断第三次打卡时间，
                if(ToolUtil.isNotEmpty(dddda.getTimeThreeNote())&&dddda.getTimeThreeNote().contains("迟到")){


                    //计算迟到分钟数
                    Double lateMinutes = compareTwoDateMinutes(shiftNote.getTimeThree() ,dddda.getTimeThree());
                    // 若迟到小于等于30 分钟，则算迟到，若迟到，大于30分钟，则不算迟到
                    if(lateMinutes <= 30){
                        lateNum ++ ;
                    }
                }
                dddda.setAttendWorkDay(STANDARD_ATTEND_WORK_DAY);
                if(lateNum == 0 ){
                    //当天打卡状态正常
                    dddda.setAttendStatus(0);
                }

                if(lateNum > 0 ){
                    //当天打卡状态异常
                    dddda.setAttendStatus(1);
                    //当天设置迟到状态异常
                    dddda.setLateNum(lateNum);
                }
            }
        }
            // 等于四次打卡
            if(listDate.size() == 4 ){

                //工作时间，等于两两工作时间只差+加出差时间
                attendWorkMinutes =  compareTwoDateMinutes(listDate.get(0),listDate.get(1))+compareTwoDateMinutes(listDate.get(2),listDate.get(3))+dddda.getRequestOutMinutes();
                dddda.setAttendWorkMinutes(attendWorkMinutes);

                // 若没有班次，则按照打卡次数计算，
                if(shiftNote.getFlag() == false ){
                    //当天打卡状态正常
                    dddda.setAttendStatus(0);
                    dddda.setAttendWorkDay(STANDARD_ATTEND_WORK_DAY);
                }
                // 若有班次，则按照班次计算，迟到问题
                if(shiftNote.getFlag() == true ){

                    // 判断第一次打卡时间，
                    if(ToolUtil.isNotEmpty(dddda.getTimeOneNote())&&dddda.getTimeOneNote().contains("迟到")){

                        //计算迟到分钟数
                        Double lateMinutes = compareTwoDateMinutes(shiftNote.getTimeOne() ,dddda.getTimeOne());

                        System.out.println("迟到时间计算--------------------------------");
                        System.out.println(sdf.format(shiftNote.getTimeOne()));
                        System.out.println(sdf.format(dddda.getTimeOne()));
                        System.out.println(lateMinutes);

                        // 若迟到小于等于30 分钟，则算迟到，若迟到，大于30分钟，则不算迟到
                        if(lateMinutes<=30){
                            lateNum ++ ;
                        }
                    }

                    // 判断第三次打卡时间，
                    if(ToolUtil.isNotEmpty(dddda.getTimeThreeNote())&&dddda.getTimeThreeNote().contains("迟到")){
                        //计算迟到分钟数
                        Double lateMinutes = compareTwoDateMinutes(shiftNote.getTimeThree() ,dddda.getTimeThree());

                        System.out.println("迟到时间计算--------------------------------");
                        System.out.println(sdf.format(shiftNote.getTimeThree()));
                        System.out.println(sdf.format(dddda.getTimeThree()));
                        System.out.println(lateMinutes);

                        // 若迟到小于等于30 分钟，则算迟到，若迟到，大于30分钟，则不算迟到

                        if(lateMinutes<=30){
                            lateNum ++ ;
                        }
                    }
                    dddda.setAttendWorkDay(STANDARD_ATTEND_WORK_DAY);
                    if(lateNum == 0 ){
                        //当天打卡状态正常
                        dddda.setAttendStatus(0);
                    }

                    if(lateNum > 0 ){
                        //当天打卡状态异常
                        dddda.setAttendStatus(1);
                        //当天设置迟到状态异常
                        dddda.setLateNum(lateNum);
                    }
                }

            }

            // 等于三次打卡
            if(listDate.size() == 3 ){

                //工作时间，等于两两工作时间只差+加出差时间
                attendWorkMinutes =  compareTwoDateMinutes(listDate.get(0),listDate.get(2))+dddda.getRequestOutMinutes();
                dddda.setAttendWorkMinutes(attendWorkMinutes);
                // 若没有班次，则按照打卡次数计算，
                if(shiftNote.getFlag() == false ){
                    dddda.setAttendWorkDay(STANDARD_ATTEND_WORK_DAY);
                    // 若没有外出，则记录打卡异常，缺卡1次
                    if(dddda.getRequestOutStatus() == 0){
                        //当天打卡状态异常
                        dddda.setAttendStatus(1);
                        //当天漏打卡1次
                        dddda.setLackAttendNum(1);
                    }

                    // 若有外出申请单据则记录打卡正常，漏打卡
                    if(dddda.getRequestOutStatus() == 1){
                        //当天打卡状态异常
                        dddda.setAttendStatus(0);
                        //当天漏打卡1次
                        dddda.setLackAttendNum(0);
                    }
                }
                // 若有班次，则按照班次计算，迟到问题
                if(shiftNote.getFlag() == true ){

                    dddda.setAttendWorkDay(STANDARD_ATTEND_WORK_DAY);
                    // 若没有外出，则记录打卡异常，缺卡1次
                    if(dddda.getRequestOutStatus() == 0){
                        //当天打卡状态异常
                        dddda.setAttendStatus(1);
                        //当天漏打卡1次
                        dddda.setLackAttendNum(1);
                    }

                    // 若有外出申请单据则记录打卡正常，漏打卡
                    if(dddda.getRequestOutStatus() == 1){
                        //当天打卡状态异常
                        dddda.setAttendStatus(0);
                        //当天漏打卡0次
                        dddda.setLackAttendNum(0);
                    }

                    // 判断第一次打卡时间，
                    if(ToolUtil.isNotEmpty(dddda.getTimeOneNote())&&dddda.getTimeOneNote().contains("迟到")){
                        //计算迟到分钟数
                        Double lateMinutes = compareTwoDateMinutes(shiftNote.getTimeOne() ,dddda.getTimeOne());
                        // 若迟到小于等于30 分钟，则算迟到，若迟到，大于30分钟，则不算迟到
                        if(lateMinutes<=30){
                            lateNum ++ ;
                        }
                    }

                    // 判断第三次打卡时间，
                    if(ToolUtil.isNotEmpty(dddda.getTimeThreeNote())&&dddda.getTimeThreeNote().contains("迟到")){
                        //计算迟到分钟数
                        Double lateMinutes = compareTwoDateMinutes(shiftNote.getTimeThree() ,dddda.getTimeThree());
                        // 若迟到小于等于30 分钟，则算迟到，若迟到，大于30分钟，则不算迟到
                        if(lateMinutes<=30){
                            lateNum ++ ;
                        }
                    }

                    if(lateNum == 0 ){
                        //当天打卡状态正常
                        dddda.setAttendStatus(0);
                    }

                    if(lateNum > 0 ){
                        //当天打卡状态异常
                        dddda.setAttendStatus(1);
                        //当天设置迟到状态异常
                        dddda.setLateNum(lateNum);
                    }
                }
            }
            //若有两次打卡记录
            if(listDate.size()==2){
                //工作时间，等于最晚时间-最早时间工作时间只差 + 加外出时间
                attendWorkMinutes =  compareTwoDateMinutes(listDate.get(0),listDate.get(1))+dddda.getRequestOutMinutes();
                dddda.setAttendWorkMinutes(attendWorkMinutes);
                // 若没有班次，则按照打卡次数计算，
                if(shiftNote.getFlag() == false ){
                    // 若没有外出，则记录打卡异常
                    if(dddda.getRequestOutStatus() == 0){
                        Double twoTimeMinutes = compareTwoDateMinutes(listDate.get(0) ,listDate.get(1));

                        if(twoTimeMinutes >= 8 ){
                            //当天打卡状态异常
                            dddda.setAttendStatus(1);
                            dddda.setAttendWorkDay(STANDARD_ATTEND_WORK_DAY);

                            //记录漏打卡次数
                            dddda.setLackAttendNum(2);
                        }

                        if(twoTimeMinutes < 8 ){
                            //当天打卡状态异常
                            dddda.setAttendStatus(1);
                            dddda.setAttendWorkDay(HALF_ATTEND_WORK_DAY);
                        }
                    }

                    // 若有外出申请单据则记录打卡正常，漏打卡
                    if(dddda.getRequestOutStatus() == 1){
                        //当天打卡状态异常
                        dddda.setAttendStatus(1);
                        dddda.setAttendWorkDay(STANDARD_ATTEND_WORK_DAY);
                    }
                }
                // 若有班次，则按照班次次数计算，
                if(shiftNote.getFlag() == true ){
                    // 若没有外出，则记录打卡异常
                    if(dddda.getRequestOutStatus() == 0){
                        //判断是否是第一次和第四次打卡，若是，则判断漏打卡两次
                        if(ToolUtil.isNotEmpty(dddda.getTimeOne())&&ToolUtil.isNotEmpty(dddda.getTimeFour())){
                            //当天打卡状态异常
                            dddda.setAttendStatus(1);
                            dddda.setAttendWorkDay(STANDARD_ATTEND_WORK_DAY);

                            //记录漏打卡次数
                            dddda.setLackAttendNum(2);
                        }
                        if(ToolUtil.isEmpty(dddda.getTimeOne())||ToolUtil.isEmpty(dddda.getTimeFour())){
                            //当天打卡状态异常
                            dddda.setAttendStatus(1);
                            dddda.setAttendWorkDay(HALF_ATTEND_WORK_DAY);
                        }
                    }

                    // 若有外出申请单据则记录打卡正常，漏打卡
                    if(dddda.getRequestOutStatus() == 1){
                        //当天打卡状态异常
                        dddda.setAttendStatus(1);
                        dddda.setAttendWorkDay(STANDARD_ATTEND_WORK_DAY);
                    }
                }
            }
            //若小于一次打卡记录
            if(1 >= listDate.size()){

                //工作时间，等于外出时间
                attendWorkMinutes = dddda.getRequestOutMinutes();

                dddda.setAttendWorkMinutes(attendWorkMinutes);
                //若有外出申请单
                if(dddda.getRequestOutStatus() == 1){
                    //当天打卡状态异常
                    dddda.setAttendStatus(1);
                    dddda.setAttendWorkDay(STANDARD_ATTEND_WORK_DAY);
                }
                // 若无外出申请单
                if(dddda.getRequestOutStatus() == 0){
                    //当天打卡状态异常
                    dddda.setAttendStatus(1);
                    dddda.setAttendWorkDay(NOT_ATTEND_WORK_DAY);
                }
            }

        // 判断前四次打卡，备注中是否有修改情况
        int abnormalChangeNum = 0;
        //第一次备注修改，
        if(ToolUtil.isNotEmpty(dddda.getTimeOneNote())&&dddda.getTimeOneNote().contains("改")){
            abnormalChangeNum ++;
        }
        //第二次备注修改，
        if(ToolUtil.isNotEmpty(dddda.getTimeTwoNote())&&dddda.getTimeTwoNote().contains("改")){
            abnormalChangeNum ++;
        }
        //第三次备注修改，
        if(ToolUtil.isNotEmpty(dddda.getTimeThreeNote())&&dddda.getTimeThreeNote().contains("改")){
            abnormalChangeNum ++;
        }
        //第四次备注修改，
        if(ToolUtil.isNotEmpty(dddda.getTimeFourNote())&&dddda.getTimeFourNote().contains("改")){
            abnormalChangeNum ++;
        }
        //第五次备注修改，
        if(ToolUtil.isNotEmpty(dddda.getTimeFiveNote())&&dddda.getTimeFiveNote().contains("改")){
            abnormalChangeNum ++;
        }
        //第六次备注修改，
        if(ToolUtil.isNotEmpty(dddda.getTimeSixNote())&&dddda.getTimeSixNote().contains("改")){
            abnormalChangeNum ++;
        }

        dddda.setAbnormalChangeNum(abnormalChangeNum);
        return dddda;
    }


    // 计算打卡次数
    private List<Date> calculateListDateAll(BtyDingdingDayAttend dddda) {
        List<Date> listDateAll = new ArrayList<Date>();
        // 若第一次卡没有漏掉
        if(ToolUtil.isNotEmpty(dddda.getTimeOne())){
            listDateAll.add(dddda.getTimeOne());
        }
        // 若第二次卡没有漏掉
        if(ToolUtil.isNotEmpty(dddda.getTimeTwo())){
            listDateAll.add(dddda.getTimeTwo());
        }
        // 若第三次卡没有漏掉
        if(ToolUtil.isNotEmpty(dddda.getTimeThree())){
            listDateAll.add(dddda.getTimeThree());
        }
        // 若第四次卡没有漏掉
        if(ToolUtil.isNotEmpty(dddda.getTimeFour())){
            listDateAll.add(dddda.getTimeFour());
        }
        // 若有第五次卡没有漏掉
        if(ToolUtil.isNotEmpty(dddda.getTimeFive())){
            listDateAll.add(dddda.getTimeFive());
        }
        // 若有第六次没有漏掉
        if(ToolUtil.isNotEmpty(dddda.getTimeSix())){
            listDateAll.add(dddda.getTimeSix());
        }

        return listDateAll;
    }

    /**
     * 判断是否有正常的班次，若有，则返回班次时间，若没有，则不返回时间
     * @param dddda
     * @return
     */
    private BtyDingdingDayAttendAttendShiftNote calculateShiftNote(BtyDingdingDayAttend dddda) {
        BtyDingdingDayAttendAttendShiftNote shiftNote = new BtyDingdingDayAttendAttendShiftNote();

        // 班次
        String attendShiftNote = dddda.getAttendShiftNote();

        // 若等于空则自由工时
        if(ToolUtil.isEmpty(attendShiftNote)){
            shiftNote.setFlag(false);
        }
        // 若等于自由工时则自由工时
        if(attendShiftNote.contains("自由工时")){
            shiftNote.setFlag(false);
        }

        if (attendShiftNote.contains("-")){
            // 获取第一个”-“数据
            int i = attendShiftNote.indexOf("-");

            String timeOneStr = attendShiftNote.substring(i - 5, i);
            Date timeOne = getTimeByDate(dddda, timeOneStr);
            shiftNote.setTimeOne(timeOne);

            String timeTwoStr = attendShiftNote.substring(i + 1, i + 6);
            if(timeTwoStr.contains("次日")){
                timeTwoStr = attendShiftNote.substring(i + 1, i + 8);
            }
            Date timeTwo = getTimeByDate(dddda, timeTwoStr);
            shiftNote.setTimeTwo(timeTwo);

            // 获取第二个”-“数据
            int i2 = attendShiftNote.indexOf("-",i+1);//s.lastIndexOf("-");
            if(i2>0){
                String timeThreeStr = attendShiftNote.substring(i2 - 5, i2);
                Date timeThree = getTimeByDate(dddda, timeThreeStr);
                shiftNote.setTimeThree(timeThree);

                String timeFourStr = attendShiftNote.substring(i2 + 1, i2 + 6);
                if(timeFourStr.contains("次日")){
                    timeFourStr = attendShiftNote.substring(i2 + 1, i2 + 8);
                }

                Date timeFour = getTimeByDate(dddda, timeFourStr);
                shiftNote.setTimeFour(timeFour);
            }
            shiftNote.setFlag(true);
        }

        //   attendShiftNote = 休息
        if(ToolUtil.isEmpty(shiftNote.getFlag())){
            shiftNote.setFlag(false) ;
        }
        return shiftNote;
    }

    /**
     * 将获取的子时间,转化为时间格式
     * @param ddda
     * @param worktime
     * @return
     */
    private Date getTimeByDate(BtyDingdingDayAttend ddda, String worktime) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdfYMD = new SimpleDateFormat("yyyy-MM-dd");

        Date date = null;
        String dateStr = sdfYMD.format(ddda.getAttendDay());
        if(ToolUtil.isNotEmpty(worktime)){
            try {

                if(worktime.indexOf("次日") == -1&&worktime.indexOf("昨日") == -1){
                    date = sdf.parse(dateStr+" "+worktime+":00");
                }
                if(worktime.indexOf("昨日") > -1){
                    date = sdf.parse(TimeUtil.getDateYestoday(ddda.getAttendDay())+" "+worktime.replace("昨日","")+":00");
                }

                if(worktime.indexOf("次日")>-1){
                    date = sdf.parse(TimeUtil.getDateTomorrow(ddda.getAttendDay())+" "+worktime.replace("次日","")+":00");
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return date;
    }


//    public static void main(String[] args) {
//        //String s="福建C班次 16:30-20:40 21:30-次日01:00";
//        String s="東更道通用班次 07:30-14:30 15:30-22:00";
//        BtyDingdingDayAttendServiceImpl  impl = new BtyDingdingDayAttendServiceImpl();
//        BtyDingdingDayAttend dddda = new BtyDingdingDayAttend();
//        dddda.setAttendShiftNote(s);
//        BtyDingdingDayAttendAttendShiftNote  shiftNote = impl.calculateShiftNote( dddda);
//        System.out.println(shiftNote.getFlag());
//    }

    /**
     * 判定两两打卡若小于15分钟，则算一次打卡
     * @param listDate
     * @return
     */
    private List<Date> judgeListDate(List<Date> listDate) {
        for(int i = listDate.size()-1;i > 0;i--){
            if( FIFTEEN_MINUTES > compareTwoDateMinutes(listDate.get(i-1),listDate.get(i))){
                if(i==1){
                    listDate.remove(i);
                }
                if(i!=1){
                    listDate.remove(i-1);
                }
            }
        }
        return listDate;
    }


    /**
     * 判断传过来的值两两只差是否是小于15分分钟
     * @param listDate 时间列表
     * @param timeNums 有几次的时间
     * @return
     */
    private boolean judgeTwoTimeLessThanFifteenMinutes(List<Date> listDate, int timeNums) {
        boolean flag = false;

        // 若有四次打卡，则对比，1-2，2-3，3-4
        if(timeNums == 4 ){
            if( FIFTEEN_MINUTES > compareTwoDateMinutes(listDate.get(0),listDate.get(1))){
                flag = true;
            }
            if( FIFTEEN_MINUTES > compareTwoDateMinutes(listDate.get(1),listDate.get(2))){
                flag = true;
            }
            if( FIFTEEN_MINUTES > compareTwoDateMinutes(listDate.get(2),listDate.get(3))){
                flag = true;
            }
        }

        //  若有三次打卡，则对比，1-2，2-3
        if(timeNums == 3 ){
            if( FIFTEEN_MINUTES > compareTwoDateMinutes(listDate.get(0),listDate.get(1))){
                flag = true;
            }
            if( FIFTEEN_MINUTES > compareTwoDateMinutes(listDate.get(1),listDate.get(2))){
                flag = true;
            }
        }


        return flag;
    }


    /**
     *  计算有几次打卡记录
     * @param dddda
     * @return
     */
    private int calculateClockInNum(BtyDingdingDayAttend dddda) {
        //当天的打卡的次数
        int timeNums = 0;
        //第一次打卡
        if(ToolUtil.isNotEmpty(dddda.getTimeOne())){
            timeNums++;
        }
        //第二次打卡
        if(ToolUtil.isNotEmpty(dddda.getTimeTwo())){
            timeNums++;
        }
        //第三次打卡
        if(ToolUtil.isNotEmpty(dddda.getTimeThree())){
            timeNums++;
        }
        //第四次打卡
        if(ToolUtil.isNotEmpty(dddda.getTimeFour())){
            timeNums++;
        }
        //第五次打卡
        if(ToolUtil.isNotEmpty(dddda.getTimeFive())){
            timeNums++;
        }
        //第六次打卡
        if(ToolUtil.isNotEmpty(dddda.getTimeSix())){
            timeNums++;
        }
        return timeNums;
    }

    /**
     * 记录两次距离最远打卡时间之差;
     * 返回分钟数
     * 注意传值必须， date2>date1
     * @param date1
     * @param date2
     * @return
     */
    private Double compareTwoDateMinutes(Date date1, Date date2) {
        long minutes = ChronoUnit.MINUTES.between(Instant.ofEpochMilli(date1.getTime()), Instant.ofEpochMilli(date2.getTime()));
        return Double.valueOf(String.valueOf(minutes));
    }

    /**
     * 比较两两只差大与半小时
     * 注意传值必须，date3>date2>date1
     * @param date1
     * @param date2
     * @param date3
     * @return
     */
    private Boolean compareTwoDateMoreThanHalfHour(Date date1, Date date2, Date date3) {
        boolean moreThanHalfHour = true;
        long minutes1 = ChronoUnit.MINUTES.between(Instant.ofEpochMilli(date1.getTime()), Instant.ofEpochMilli(date2.getTime()));

        long minutes2 = ChronoUnit.MINUTES.between(Instant.ofEpochMilli(date2.getTime()), Instant.ofEpochMilli(date3.getTime()));

        if(minutes1<THREE_WORKING_MINUTES_POOR){
            moreThanHalfHour = false;
        }
        if(minutes2<THREE_WORKING_MINUTES_POOR){
            moreThanHalfHour = false;
        }
        return moreThanHalfHour;
    }

    /**
     * // 若有外出申请单，则工作时间=工作时间+外出申请单时间，工作时长
     * @param dddda
     * @return
     */
    private Double getAttendWorkMinutes(BtyDingdingDayAttend dddda) {
        //获取工作时长分钟；
        Double attendWorkMinutes = dddda.getWorkTime();
        // 若有外出申请单，则工作时间=工作时间+外出申请单时间，工作时长
        if(dddda.getRequestOutStatus() == 1){
            String requestNote =  dddda.getRequestNote();
            String[] requestNoteArr = requestNote.split(",");
            for(String note:requestNoteArr){
                //如果有外出，计算外出时间，算正常出勤的工时
                if(note.contains("外出")){
                    //外出03-09 07:00到03-11 07:00 27小时,外出03-11 07:30到03-13 07:30 27小时
                    String[] noteArr = note.split(" ");
                    if(noteArr[3].contains("小时")){
                        Double noteTime = Double.valueOf(noteArr[3].replace("小时",""));
                        attendWorkMinutes += noteTime*60;
                    }
                }
            }
        }
        return attendWorkMinutes;
    }


    /**
     * 将这个员工获取的这个月的考勤数据存储到列表中；
     * @param empAttendListMonthAll
     * @param BtyDingdingDayEmp
     * @param list
     * @return
     */
    private List<BtyDingdingDayAttend> setEmpAttendListMonthAllInfo(List<BtyDingdingDayAttend> empAttendListMonthAll, BtyDingdingDayEmp BtyDingdingDayEmp, List<Map> list) {

        for(Map mapTmp1:list){
            List<Map> list1 = (List) mapTmp1.get("column_vals");//31天
            Map mapTmp11 = (Map) mapTmp1.get("column_vo");
            Integer colid = (Integer) mapTmp11.get("id");
            switch(colid){
                case 7100704:
                    //logger.info("7100704:工作时长");
                    Map<Date,String> mapVals04 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setWorkTime(Double.valueOf(mapVals04.get(ddda.getAttendDay())));
                    }
                    break;
                case 7100705:
                    //logger.info("7100705:迟到次数");
                    Map<Date,String> mapVals05 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setLateNum(Integer.valueOf(mapVals05.get(ddda.getAttendDay())));
                    }
                    break;
                case 7100706:
                    //logger.info("7100706:迟到时长");
                    Map<Date,String> mapVals06 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setLateMinutes(Double.valueOf(mapVals06.get(ddda.getAttendDay())));
                    }
                    break;
                case 7100710:
                    //logger.info("7100710:早退次数");
                    Map<Date,String> mapVals10 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setLeaveEarlyNum(Integer.valueOf(mapVals10.get(ddda.getAttendDay())));
                    }
                    break;
                case 7100711:
                    //logger.info("7100711:早退时长");
                    Map<Date,String> mapVals11 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setLeaveEarlyMinutes(Double.valueOf(mapVals11.get(ddda.getAttendDay())));
                    }
                    break;
                case 7100724:
                    //logger.info("7100724:第一次打卡时间");
                    Map<Date,String> mapVals24 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setTimeOne( getTimeInMap(ddda,mapVals24));
                    }
                    break;
                case 7100726:
                    //logger.info("7100726:第二次打卡时间");
                    Map<Date,String> mapVals26 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setTimeTwo( getTimeInMap(ddda,mapVals26));
                    }
                    break;
                case 7100728:
                    //logger.info("7100728:第三次打卡时间");
                    Map<Date,String> mapVals28 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setTimeThree(getTimeInMap(ddda,mapVals28));
                    }
                    break;
                case 7100730:
                    //logger.info("7100730:第四次打卡时间");
                    Map<Date,String> mapVals30 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setTimeFour(getTimeInMap(ddda,mapVals30));
                    }
                    break;
                case 7100732:
                    //logger.info("7100732:第五次打卡时间");
                    Map<Date,String> mapVals32 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setTimeFive(getTimeInMap(ddda,mapVals32));
                    }
                    break;
                case 7100734:
                    //logger.info("7100734:第六次打卡时间");
                    Map<Date,String> mapVals34 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setTimeSix(getTimeInMap(ddda,mapVals34));
                    }
                    break;
                case 7100736:
                    //logger.info("7100736:关联表单日期及详情");
                    Map<Date,String> mapVals36 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        //申请单详情
                        String requestNote = mapVals36.get(ddda.getAttendDay());

                        if(ToolUtil.isNotEmpty(requestNote)){
                            ddda.setRequestStatus(1);
                            ddda.setRequestNote(requestNote);
                            //单据不止有一个，若单据有多个，单独处理
                            String[] requestNoteArr = requestNote.split(",");
                            for(String note:requestNoteArr){
                                //如果有外出，计算外出时间，算正常出勤的工时
                                if(note.contains("外出")){
                                    //将外出的状态记录上
                                    ddda.setRequestOutStatus(1);

                                }
                                //如果有假，计算假期的时间
                                if(note.contains("假")){
                                    //将假期的状态记录上
                                    ddda.setAskLeaveStatus(1);
                                }
                            }
                        }
                    }
                    break;
                case 7100701:
                    //logger.info("7100701:出勤班次");
                    Map<Date,String> mapVals01 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setAttendShift(mapVals01.get(ddda.getAttendDay()));
                    }
                    break;
                case 7100715:
                    //logger.info("7100715:出差时长");
                    Map<Date,String> mapVals15 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setAttendOut(Double.valueOf(mapVals15.get(ddda.getAttendDay())));
                    }
                    break;
                case 7100716:
                    //logger.info("7100716:外出时长");
                    Map<Date,String> mapVals16 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        if(ToolUtil.isNotEmpty(ddda.getAttendDay())){
                            ddda.setRequestOut(Double.valueOf(mapVals16.get(ddda.getAttendDay())));
                            ddda.setRequestOutMinutes(Double.valueOf(mapVals16.get(ddda.getAttendDay()))*60);
                        }
                    }
                    break;
                case 7100723:
                    //logger.info("7100723:班次");
                    Map<Date,String> mapVals23 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setAttendShiftNote(mapVals23.get(ddda.getAttendDay()));
                    }
                    break;



                case 7100725:
                    //logger.info("7100725:第一次打卡结果");
                    Map<Date,String> mapVals25 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setTimeOneNote(mapVals25.get(ddda.getAttendDay()));
                    }
                    break;

                case 7100727:
                    //logger.info("7100727:第二次打卡结果");
                    Map<Date,String> mapVals27 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setTimeTwoNote(mapVals27.get(ddda.getAttendDay()));
                    }
                    break;

                case 7100729:
                    //logger.info("7100729:第三次打卡结果");
                    Map<Date,String> mapVals29 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setTimeThreeNote(mapVals29.get(ddda.getAttendDay()));
                    }
                    break;

                case 7100731:
                    //logger.info("7100731:第四次打卡结果");
                    Map<Date,String> mapVals31 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setTimeFourNote(mapVals31.get(ddda.getAttendDay()));
                    }
                    break;

                case 7100733:
                    //logger.info("7100733:第五次打卡结果");
                    Map<Date,String> mapVals33 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setTimeFiveNote(mapVals33.get(ddda.getAttendDay()));
                    }
                    break;

                case 7100735:
                    //logger.info("7100735:第四次打卡结果");
                    Map<Date,String> mapVals35 = setValsListToMap(list1);
                    for(BtyDingdingDayAttend ddda:empAttendListMonthAll){
                        ddda.setTimeSixNote(mapVals35.get(ddda.getAttendDay()));
                    }
                    break;

                default:
                    //logger.error("此处默认数据--------------------------------");
                    //logger.error("此处默认数据："+list1.toString());
                    //logger.error("此处默认数据--------------------------------");
            }

        }
        return empAttendListMonthAll;
    }







    /**
     * 获取，此员工，这个月，多少天内，默认创建多少条考勤数据；
     * @param BtyDingdingDayEmp
     * @param lastMonth
     * @return
     */
    private List<BtyDingdingDayAttend> setEmpAttendListMonthAllBase(BtyDingdingDayEmp BtyDingdingDayEmp, String lastMonth) {

        String thisMonth = lastMonth+"01";
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        Date date = new Date();
        try {
            date = format.parse(thisMonth);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        List<String> monthLastDayNum = TimeUtil.getMonthLastDayStrNum(date);

        List<BtyDingdingDayAttend> AttendListAll = new ArrayList<BtyDingdingDayAttend>(){};
        Date nowDate = new Date();
        try {
            for(String day:monthLastDayNum){
                BtyDingdingDayAttend ddda = new BtyDingdingDayAttend();
                ddda.setId(UUIDUtils.getId());
                ddda.setAttendYearMonth(lastMonth);
                ddda.setEmpId(BtyDingdingDayEmp.getEmpId());
                ddda.setEmpName(BtyDingdingDayEmp.getEmpName());
                ddda.setAttendDay(sdfYMD.parse(day));
                ddda.setCreateTime(nowDate);
                ddda.setAttendStatus(0); //出勤状态默认正常
                ddda.setAttendWorkDay(Double.valueOf(0)); //出天数默认为0天
                ddda.setLateNum(0); //迟到默认0次
                ddda.setLeaveEarlyNum(0); //早退默认0次
                ddda.setLackAttendNum(0); // 当天漏打卡次数;漏打卡次数默认0次
                ddda.setRequestStatus(0); // 外出申请单状态默认0，没有
                ddda.setRequestOutStatus(0); // 外出申请单状态默认0，没有
                ddda.setAskLeaveStatus(0);// 请假状态次数默认0,没有
                ddda.setDelFlag(0);// 默认数据未被删除

                AttendListAll.add(ddda);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return AttendListAll;
    }


    /**
     * 将获取的子时间list，转化为map
     * key 为时间
     * value 打卡时间
     * 值可为空，值中存在次日，则打卡时间转化为获取时间的下一天
     * @param ddda
     * @param mapVals
     * @return
     */
    private Date getTimeInMap(BtyDingdingDayAttend ddda, Map<Date, String> mapVals) {
        Date date = null;
        String dateStr = sdfYMD.format(ddda.getAttendDay());
        if(ToolUtil.isNotEmpty(mapVals.get(ddda.getAttendDay()))){
            try {

                if(mapVals.get(ddda.getAttendDay()).indexOf("次日") == -1&&mapVals.get(ddda.getAttendDay()).indexOf("昨日") == -1){
                    date = sdf.parse(dateStr+" "+mapVals.get(ddda.getAttendDay())+":00");
                }
                if(mapVals.get(ddda.getAttendDay()).indexOf("昨日") > -1){
                    date = sdf.parse(TimeUtil.getDateYestoday(ddda.getAttendDay())+" "+mapVals.get(ddda.getAttendDay()).replace("昨日","")+":00");
                }

                if(mapVals.get(ddda.getAttendDay()).indexOf("次日")>-1){
                    date = sdf.parse(TimeUtil.getDateTomorrow(ddda.getAttendDay())+" "+mapVals.get(ddda.getAttendDay()).replace("次日","")+":00");
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return date;
    }






    /**
     *  将数据批量保存
     * @param list
     * @return
     */
    public int simpleSqlInsertBatch(List<BtyDingdingDayAttend> list) {
        if (list == null || list.size() < 1) {
            return 0;
        }
        // 如果提交的列表条数小于提交阀值
        List<BtyDingdingDayAttend>[] splitLists = splitLists(list, 30);
        for (List<BtyDingdingDayAttend> tempList : splitLists) {
            this.baseMapper.addList(tempList);
            //this.saveBatch(tempList);
        }
        return list.size();
    }

    /**
     * 对一个列表按照splitNum进行分割。
     *
     * @param lists
     * @param splitNum
     * @param <T>
     * @return
     */
    public static <T>List<BtyDingdingDayAttend>[] splitLists(List<BtyDingdingDayAttend> lists, int splitNum) {
        int listSize;
        if (lists == null || (listSize = lists.size()) < 1) {
            return new ArrayList[0];
        }
        int length = listSize % splitNum == 0 ? listSize / splitNum : listSize / splitNum + 1;
        // 这里面如果用ArrayList，会在50行报错。ArrayList list = new List();这样会报错。
        List<BtyDingdingDayAttend>[] results = new List[length];
        int fromIndex, toIndex;
        for (int i = 0; i < length; i++) {
            fromIndex = i * splitNum;
            toIndex = (fromIndex + splitNum) > listSize ? listSize : (fromIndex + splitNum);
            results[i] = lists.subList(fromIndex, toIndex);
        }
        return results;
    }



    /**
     * 将列表值数据list，转化为map
     * key 时间
     * value 数据
     * 数据可为空
     * @param list
     * @return
     */
    private Map<Date, String> setValsListToMap(List<Map> list) {
        Map<Date,String> mapResult = new HashMap<Date,String>();
        try {
            for(Map<String,String> map :list){
                String value = map.get("value");
                String date = map.get("date");
                Date dateSdf = sdf.parse(date);
                mapResult.put(dateSdf,value);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return mapResult;
    }

    private Serializable getKey(BtyDingdingDayAttendParam param){
        return param.getId();
    }

    private Page getPageContext() {
        return LayuiPageFactory.defaultPage();
    }

    private BtyDingdingDayAttend getOldEntity(BtyDingdingDayAttendParam param) {
        return this.getById(getKey(param));
    }

    private BtyDingdingDayAttend getEntity(BtyDingdingDayAttendParam param) {
        BtyDingdingDayAttend entity = new BtyDingdingDayAttend();
        ToolUtil.copyProperties(param, entity);
        return entity;
    }

}

@Data
class BtyDingdingDayAttendAttendShiftNote implements Serializable {

    private static final long serialVersionUID = 1L;

    // 是否标准的班次
    private Boolean flag;

    private Date timeOne;

    private Date timeTwo;

    private Date timeThree;

    private Date timeFour;
}